<template>
  <div class="file-upload">
    <el-upload
      class="upload-demo"
      :action="action"
      :on-success="handleUploadSuccess"
      :on-error="handleUploadError"
      :before-upload="beforeUpload"
      :accept="accept"
      :limit="limit"
      :list-type="listType"
      :disabled="disabled"
      :multiple="multiple"
      :show-file-list="showFileList"
      :http-request="customUpload"
    >
      <el-button type="primary" :disabled="disabled">{{ buttonText }}</el-button>
      <template #tip>
        <div class="el-upload__tip" v-if="showTip">
          {{ tipText }}
        </div>
      </template>
    </el-upload>
    
    <!-- 显示已上传的文件信息 -->
    <div class="file-preview" v-if="localFileUrl">
      <div class="file-info" @click="handleViewFile">
        <el-icon class="file-icon"><Document /></el-icon>
        <div class="file-name">{{ getFileName(localFileUrl) }}</div>
        <div class="file-action-tip">点击查看文件</div>
      </div>
      <div class="file-delete-btn" @click.stop="handleDeleteFile">
        <el-icon><Delete /></el-icon>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { Delete, Document } from '@element-plus/icons-vue'

const props = defineProps({
  // 上传地址
  action: {
    type: String,
    required: true
  },
  // 文件类型限制
  accept: {
    type: String,
    default: '.pdf,.doc,.docx,.xls,.xlsx,.txt,.ppt,.pptx,.csv'
  },
  // 上传数量限制
  limit: {
    type: Number,
    default: 1
  },
  // 列表类型
  listType: {
    type: String,
    default: 'text'
  },
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false
  },
  // 是否多选
  multiple: {
    type: Boolean,
    default: false
  },
  // 是否显示文件列表
  showFileList: {
    type: Boolean,
    default: true
  },
  // 按钮文字
  buttonText: {
    type: String,
    default: '点击上传'
  },
  // 是否显示提示
  showTip: {
    type: Boolean,
    default: true
  },
  // 提示文字
  tipText: {
    type: String,
    default: '支持上传常见文档文件，且不超过20MB'
  },
  // 文件大小限制（MB）
  fileSize: {
    type: Number,
    default: 20
  },
  // 已上传的文件URL
  fileUrl: {
    type: String,
    default: ''
  },
  // 上传系统渠道
  sysUploadType: {
    type: String,
    default: 'system'
  }
})

const emit = defineEmits(['update:modelValue', 'success', 'error'])

// 本地文件URL
const localFileUrl = ref('')

// 监听fileUrl变化
watch(() => props.fileUrl, (newVal) => {
  if (newVal) {
    // 检查是否是对象类型并包含url属性
    if (typeof newVal === 'object' && newVal.url) {
      // 检查是否已经包含http，如果不包含则添加baseUrl
      if (newVal.url.startsWith('http')) {
        localFileUrl.value = newVal.url
      } else {
        // 根据需要调整URL
        localFileUrl.value = import.meta.env.VITE_API_URL + newVal.url
      }
    } else if (typeof newVal === 'string') {
      // 直接字符串处理
      if (newVal.startsWith('http')) {
        localFileUrl.value = newVal
      } else {
        localFileUrl.value = import.meta.env.VITE_API_URL + newVal
      }
    }
  } else {
    localFileUrl.value = ''
  }
})

// 初始化时设置文件URL
if (props.fileUrl) {
  // 检查是否是对象类型并包含url属性
  if (typeof props.fileUrl === 'object' && props.fileUrl.url) {
    // 检查是否已经包含http，如果不包含则添加baseUrl
    if (props.fileUrl.url.startsWith('http')) {
      localFileUrl.value = props.fileUrl.url
    } else {
      localFileUrl.value = import.meta.env.VITE_API_URL + props.fileUrl.url
    }
  } else if (typeof props.fileUrl === 'string') {
    // 直接字符串处理
    if (props.fileUrl.startsWith('http')) {
      localFileUrl.value = props.fileUrl
    } else {
      localFileUrl.value = import.meta.env.VITE_API_URL + props.fileUrl
    }
  }
}

// 获取文件名
const getFileName = (url) => {
  if (!url) return ''
  const parts = url.split('/')
  return parts[parts.length - 1]
}

// 处理查看文件
const handleViewFile = () => {
  if (localFileUrl.value) {
    window.open(localFileUrl.value, '_blank')
  }
}

// 处理删除文件
const handleDeleteFile = (event) => {
  // 阻止事件冒泡
  event?.stopPropagation()
  
  // 清空本地文件URL
  localFileUrl.value = ''
  
  // 触发错误事件，通知父组件文件已删除
  emit('error')
  
  ElMessage.success('文件已删除')
}

// 自定义上传方法
const customUpload = (options) => {
  if (options.file) {
    // 创建表单数据
    const formData = new FormData()
    // 添加文件到FormData
    formData.append('files', options.file)
    // // 添加上传类型到FormData
    // if (props.sysUploadType && props.sysUploadType.trim() !== '') {
    //   formData.append('sysUploadType', props.sysUploadType)
    // }
    
    // 使用原生XHR
    const xhr = new XMLHttpRequest()
    
    // 打开连接
    xhr.open('POST', options.action, true)
    
    // 获取token并设置Authorization header
    const token = localStorage.getItem('token')
    if (token) {
      xhr.setRequestHeader('Authorization', `Bearer ${token}`)
    }
    
    // 设置headers - 不设置Content-Type，让浏览器自动设置multipart/form-data的boundary
    if (options.headers) {
      Object.keys(options.headers).forEach(key => {
        xhr.setRequestHeader(key, options.headers[key])
      })
    }
    
    // 只监听readyState变化来处理上传完成和错误
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4) {
        if (xhr.status >= 200 && xhr.status < 300) {
          const response = JSON.parse(xhr.responseText)
          if (options.onSuccess) {
            options.onSuccess(response)
          }
        } else {
          const error = new Error(`Upload failed with status ${xhr.status}`)
          console.log(error)
          if (options.onError) {
            options.onError(error)
          }
        }
      }
    }
    
    // 直接发送请求
    xhr.send(formData)
  }
}

// 上传成功
const handleUploadSuccess = (response, uploadFile) => {
  const fileUrl = response.data
  localFileUrl.value = fileUrl
  emit('success', fileUrl)
  ElMessage.success('上传成功')
}

// 上传失败
const handleUploadError = (error) => {
  localFileUrl.value = ''
  emit('error', error)
  ElMessage.error('上传失败，请重试')
}

// 上传前校验
const beforeUpload = (file) => {
  // 检查文件大小
  const isLtLimit = file.size / 1024 / 1024 < props.fileSize
  
  if (!isLtLimit) {
    ElMessage.error(`上传文件大小不能超过 ${props.fileSize}MB!`)
    return false
  }
  
  // 如果有接受类型限制，可以在这里进一步检查文件类型
  if (props.accept && props.accept !== '*') {
    const extension = file.name.split('.').pop().toLowerCase()
    const acceptList = props.accept.split(',').map(type => 
      type.trim().toLowerCase().replace('.', '')
    )
    
    if (!acceptList.includes(extension)) {
      ElMessage.error(`只能上传${props.accept}格式的文件!`)
      return false
    }
  }
  
  return true
}
</script>

<style scoped>
.file-upload {
  display: inline-block;
}

.file-preview {
  margin-top: 10px;
  position: relative;
  display: inline-block;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  padding: 10px;
  width: 200px;
}

.file-info {
  display: flex;
  flex-direction: column;
  align-items: center;
  cursor: pointer;
  transition: all 0.3s;
}

.file-info:hover {
  opacity: 0.8;
}

.file-icon {
  font-size: 24px;
  color: #409eff;
  margin-bottom: 5px;
}

.file-name {
  font-size: 14px;
  color: #303133;
  margin-bottom: 5px;
  word-break: break-all;
  text-align: center;
  max-width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-action-tip {
  font-size: 12px;
  color: #909399;
  text-align: center;
}

.file-delete-btn {
  position: absolute;
  top: -8px;
  right: -8px;
  background-color: #f56c6c;
  color: white;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  font-size: 12px;
  z-index: 1;
  opacity: 0.8;
  transition: all 0.3s;
}

.file-delete-btn:hover {
  opacity: 1;
  transform: scale(1.1);
}
</style>
